package com.utils.aes.convert;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.utils.aes.Aes;
import com.utils.enums.Code;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 用于 JSON 序列化和反序列化， @JSONField(serializeUsing = AesLongArrayJsonConvert.Serializer.class, deserializeUsing = AesLongArrayJsonConvert.Deserializer.class)
 *
 * @author 谢长春 2022-02-06
 */
@Slf4j
public class AesLongArrayJsonConvert {
    public static class Serializer implements ObjectSerializer {
        @Override
        public void write(JSONSerializer jsonSerializer, Object value, Object fieldName, Type fieldType, int features) throws IOException {
            if (Objects.isNull(value)) {
                return;
            }
            if (log.isDebugEnabled()) {
                log.debug("加密:{}:{}", fieldName, value);
            }
            jsonSerializer.write(Aes.encrypt(Stream.of(value).map(Objects::toString).collect(Collectors.toList())));
        }
    }

    public static class Deserializer implements ObjectDeserializer {
        @SuppressWarnings("unchecked")
        @Override
        public <T> T deserialze(DefaultJSONParser defaultJSONParser, Type fieldType, Object fieldName) {
            final List<String> list = defaultJSONParser.parseArray(String.class);
            if (Objects.isNull(list)) {
                return null;
            }
            if (log.isDebugEnabled()) {
                log.debug("解密:{}:{}", fieldName, list);
            }
            try {
                return (T) Aes.decrypt(list).stream().map(Long::parseLong).toArray(Long[]::new);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw Code.A00003.toCodeException(String.join(",", list));
            }
        }

        @Override
        public int getFastMatchToken() {
            return JSONToken.LBRACKET;
        }
    }

}
